<?php

namespace app\command;

use app\model\DistributionSetting;
use app\model\Order;
use app\model\User;
use app\model\UserInvite;
use app\model\UserUpgradeLogModel;
use Exception;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
use think\facade\Log;
use util\Logger;

class UserUpgradeCommand extends Command
{
	protected function configure()
	{
		$this->setName('user-upgrade')
			->setDescription('检查用户升级');
	}

	protected function execute(Input $input, Output $output)
	{
		Log::init([
			'type'      => 'file',
			'path'      => app()->getRootPath() . 'runtime/log/userUpgrade/',
			'level'     => ['info', 'error', 'sql', 'alert'],
			'max_files' => 10,
			'file_size' => 1024 * 1024 * 100,
		]);

		// TODO 临时解决方案，后续需要改为消息队列方式，或者临时计数表方式
		// 升级v2
		$this->upgradeV2();
		// 升级v3
		$this->upgradeV3();
		// v3降级
		$this->upgradeV3toV2();
	}


	public function upgradeV2(): void
	{
		$setting = DistributionSetting::where('uuid', 'setting')->find();
		if (!$setting) {
			return;
		}
		if ($setting['task_condition'] == 0) {
			return;
		}
		$taskCondition = $setting['task_condition'];
		$level         = json_decode($setting['value'], true);

		// TODO 后续用户多了需要改逻辑，不能扫用户全表
		// 已结算订单数量
		$userOrderCountData = (new Order())
			->field('user_id, count(*) as order_count')
			->where('commission_status', '=', '100')
			->group('user_id')
			->select()
			->toArray();
		$orderUserIds       = array_column($userOrderCountData, 'user_id');
		$userOrderCount     = array_column($userOrderCountData, 'order_count', 'user_id');

		// 邀请人数
		$userInviteCountData = (new UserInvite())
			->field('token, count(*) as invite_count')
			->group('token')
			->select()
			->toArray();
		$inviteUserTokenList = array_filter(array_column($userInviteCountData, 'token'));
		$userInviteCount     = array_column($userInviteCountData, 'invite_count', 'token');

		// 查询下单用户列表
		$orderUserList = User::field('id,token, level, total, invite_count, privilege_time')
			->where('id', 'in', $orderUserIds)
			->where('level', User::LEVEL_V1)
			->where('agent_id', 0)
			->select()
			->toArray();

		// 查询邀请用户列表
		$inviteUserList = User::field('id,token, level, total, invite_count, privilege_time')
			->where('token', 'in', $inviteUserTokenList)
			->where('level', User::LEVEL_V1)
			->where('agent_id', 0)
			->select()
			->toArray();
		// 合并数组并去重
		$userList = array_unique(array_merge($orderUserList, $inviteUserList), SORT_REGULAR);

		foreach ($userList as $user) {
			try {
				// 如果等级为 1 则 升级为2
				$orderCount  = $level[1]['order_count'];
				$inviteCount = $level[1]['invite_count'];

				$updateUserData       = [];
				$createUserUpgradeLog = [
					'user_id'      => $user['id'],
					'type'         => UserUpgradeLogModel::TYPE_UPGRADE,
					'before_level' => User::LEVEL_V1,
					'after_level'  => User::LEVEL_V2,
					'created_at'   => date('Y-m-d H:i:s'),
					'updated_at'   => date('Y-m-d H:i:s'),
				];
				if ($taskCondition == 1) {
					// 邀请人数满足
					if (isset($userInviteCount[$user['token']]) && $userInviteCount[$user['token']] >= $inviteCount) {
						$updateUserData['level']             = User::LEVEL_V2;
						$createUserUpgradeLog['source_type'] = UserUpgradeLogModel::SOURCE_TYPE_INVITE_UPGRADE;
					}

					// 下单个数满足
					if (isset($userOrderCount[$user['id']]) && $userOrderCount[$user['id']] >= $orderCount) {
						$updateUserData['level']             = User::LEVEL_V2;
						$createUserUpgradeLog['source_type'] = UserUpgradeLogModel::SOURCE_TYPE_CRATE_ORDER_UPGRADE;
					}

				} else {
					// 邀请人数 && 下单个数满足
					if (isset($userOrderCount[$user['id']]) && $userOrderCount[$user['id']] >= $orderCount && isset($userInviteCount[$user['token']]) && $userInviteCount[$user['token']] >= $inviteCount) {
						$updateUserData['level']             = User::LEVEL_V2;
						$createUserUpgradeLog['source_type'] = UserUpgradeLogModel::SOURCE_TYPE_INVITE_AND_CREATE_ORDER_UPGRADE;
					}
				}

				// 有改动则更新
				if ($updateUserData) {
					DB::transaction(function () use ($user, $createUserUpgradeLog, $updateUserData) {
						User::where('id', $user['id'])->update($updateUserData);
						UserUpgradeLogModel::create($createUserUpgradeLog);
					});
				}
			} catch (Exception $e) {
				Log::error('升级v2失败', [
					'message' => $e->getMessage(),
					'line'    => $e->getLine(),
					'file'    => $e->getFile(),
				]);
			}
		}
	}

	public function upgradeV3(): void
	{
		$setting = DistributionSetting::where('uuid', 'setting')->find();
		if (!$setting) {
			return;
		}
		if ($setting['task_condition'] == 0) {
			return;
		}
		$task_condition = $setting['task_condition'];
		$level          = json_decode($setting['value'], true);

		// 当月已结算订单数量
		$user_order_count_data = (new Order())->whereTime('create_time', 'month')
			->field('user_id, count(*) as order_count')
			->where('commission_status', '=', '100')
			->group('user_id')
			->select()
			->toArray();
		$orderUserIds          = array_column($user_order_count_data, 'user_id');
		$user_order_count      = array_column($user_order_count_data, 'order_count', 'user_id');

		// 当月邀请人数
		$user_invite_count_data = (new UserInvite())->whereTime('create_time', 'month')
			->field('token, count(*) as invite_count')
			->group('token')
			->select()
			->toArray();
		$inviteUserTokenList    = array_filter(array_column($user_invite_count_data, 'token'));
		$user_invite_count      = array_column($user_invite_count_data, 'invite_count', 'token');


		// 查询下单用户列表
		$orderUserList = User::field('id,token, level, total, invite_count, privilege_time')
			->where('id', 'in', $orderUserIds)
			->where('level', User::LEVEL_V2)
			->where('agent_id', 0)
			->select()
			->toArray();

		// 查询邀请用户列表
		$inviteUserList = User::field('id,token, level, total, invite_count, privilege_time')
			->where('token', 'in', $inviteUserTokenList)
			->whereIn('level', [User::LEVEL_V2, User::LEVEL_V3])
			->where('agent_id', 0)
			->select()
			->toArray();
		// 合并数组并去重
		$userList = array_unique(array_merge($orderUserList, $inviteUserList), SORT_REGULAR);

		$nextMonthFirstDayTimestamp = strtotime('first day of next month 00:00:00');

		foreach ($userList as $user) {
			try {
				// 本月已经升级为V3，不处理，直接跳过
				if ($user['privilege_time'] > $nextMonthFirstDayTimestamp) {
					continue;
				}

				// 如果等级为2 则 升级为 3， 如果等级为3并且有效时间小于下个月月初时间 则更新等级和有效时间
				$levelTime = $level[2]['day'] * 86400;

				$orderCount           = $level[2]['order_count'];
				$inviteCount          = $level[2]['invite_count'];
				$orderTotal           = $level[1]['order_count'] + $level[2]['order_count'];
				$inviteTotal          = $level[1]['invite_count'] + $level[2]['invite_count'];
				$expiredTime          = $nextMonthFirstDayTimestamp + $levelTime;
				$updateUserData       = [];
				$createUserUpgradeLog = [
					'user_id'      => $user['id'],
					'type'         => UserUpgradeLogModel::TYPE_UPGRADE,
					'before_level' => User::LEVEL_V2,
					'after_level'  => User::LEVEL_V3,
					'expired_at'   => date('Y-m-d H:i:s', $expiredTime),
					'created_at'   => date('Y-m-d H:i:s'),
					'updated_at'   => date('Y-m-d H:i:s'),
				];

				if ($task_condition == 1) {
					// 当月下单数量大于等于 v3数量 并且 下单总数量大于 v2 + v3的数量，则升级
					if (isset($user_order_count[$user['id']]) && $user_order_count[$user['id']] >= $orderCount) {
						// 查询下单总数量
						$orderTotalNum = Order::where('user_id', $user['id'])
							->where('commission_status', Order::COMMISSION_STATUS_COMPLETE)
							->count();
						// 判断总数量是否大于等于 v2 + v3的数量
						if ($orderTotalNum >= $orderTotal) {
							$createUserUpgradeLog['source_type'] = UserUpgradeLogModel::SOURCE_TYPE_CRATE_ORDER_UPGRADE;
							$updateUserData['level']             = User::LEVEL_V3;
							$updateUserData['privilege_time']    = $expiredTime;
						}
					}

					// 当月邀请数量大于等于 v2数量 + v3数量，则直接升级
					if (isset($user_invite_count[$user['token']]) && $user_invite_count[$user['token']] >= $inviteCount) {
						// 查询邀请总数量
						$inviteTotalNum = UserInvite::where('token', $user['token'])->count();
						// 判断总数量是否大于等于 v2 + v3的数量
						if ($inviteTotalNum >= $inviteTotal) {
							$createUserUpgradeLog['source_type'] = UserUpgradeLogModel::SOURCE_TYPE_INVITE_UPGRADE;
							$updateUserData['level']             = User::LEVEL_V3;
							$updateUserData['privilege_time']    = $expiredTime;
						}
					}
				} else {
					if ($user_order_count[$user['id']] && $user_order_count[$user['id']] >= $orderCount && $user_invite_count[$user['token']] && $user_invite_count[$user['token']] >= $inviteCount) {
						// 查询下单总数量
						$orderTotalNum = Order::where('user_id', $user['id'])
							->where('commission_status', Order::COMMISSION_STATUS_COMPLETE)
							->count();

						// 查询邀请总数量
						$inviteTotalNum = UserInvite::where('token', $user['token'])->count();
						if ($orderTotalNum >= $orderTotal && $inviteTotalNum > $inviteTotal) {
							$createUserUpgradeLog['source_type'] = UserUpgradeLogModel::SOURCE_TYPE_INVITE_AND_CREATE_ORDER_UPGRADE;
							$updateUserData['level']             = User::LEVEL_V3;
							$updateUserData['privilege_time']    = $expiredTime;
						}
					}
				}

				// 如果有改动，则更新
				if ($updateUserData) {
					// 更新用户等级，并且添加用户等级变更记录
					DB::transaction(function () use ($user, $updateUserData, $createUserUpgradeLog) {
						User::where('id', $user['id'])->update($updateUserData);
						UserUpgradeLogModel::create($createUserUpgradeLog);
					});
				}
			} catch (Exception $e) {
				Logger::error($e->getMessage());
			}
		}
	}

	public function upgradeV3toV2(): void
	{
		// 查询v3等级已过期并且未降级的用户
		$userIds = User::where('level', User::LEVEL_V3)
			->where(sprintf('privilege_time < %s', time()))
			->column('id');

		// 循环处理用户降级，并且添加等级变化记录
		foreach ($userIds as $userId) {
			try {
				DB::transaction(function () use ($userId) {
					// 变更用户等级，从 V3 -> V2
					User::where('id', $userId)->update([
						'level' => User::LEVEL_V2,
					]);

					// 添加等级变化记录
					UserUpgradeLogModel::create([
						'user_id'      => $userId,
						'type'         => UserUpgradeLogModel::TYPE_DOWNGRADE,
						'source_type'  => UserUpgradeLogModel::SOURCE_TYPE_EXPIRE_DOWNGRADE,
						'before_level' => User::LEVEL_V3,
						'after_level'  => User::LEVEL_V2,
						'created_at'   => date('Y-m-d H:i:s'),
						'updated_at'   => date('Y-m-d H:i:s'),
					]);
				});
			} catch (Exception $e) {
				Log::error('处理失败', [$e]);
			}
		}
	}
}
